package com.kuaimacode.kframework.code.utils;

import com.kuaimacode.kframework.code.enums.FieldType;
import org.apache.commons.lang3.StringUtils;

import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 代码拼接工具
 * @author Administrator
 * @date 2018/10/23
 */
public class CodeUtil {
    private static StringBuilder builder;
    private static Set<String> imports;
    private static Set<String> javaxImports;
    private static Set<String> javaImports;
    private static Set<String> importAll;
    public static String lineBreak = System.getProperty("line.separator");
    public static String packageName;

    /**
     * 创建一个StringBuilder对象
     */
    public static void create(){
        builder = new StringBuilder();
        imports = new TreeSet<>();
        javaxImports = new TreeSet<>();
        javaImports = new TreeSet<>();
        importAll = new TreeSet<>();
    }

    /**
     * 设置包路径
     */
    public static void setPackageName(String packageName){
        CodeUtil.packageName = packageName;
    }

    /**
     * 向后添加代码
     */
    public static StringBuilder append(String code){
        return builder.append(code);
    }

    /**
     * 向后添加代码
     */
    public static StringBuilder br(){
        return builder.append(lineBreak);
    }

    /**
     * 添加一行代码
     * @param code 代码
     */
    public static StringBuilder line(String code){
        return builder.append(code).append(";").append(lineBreak);
    }

    /**
     * 添加一行代码，不加分号
     * @param code 代码
     */
    public static StringBuilder lineNo(String code){
        return builder.append(code).append(lineBreak);
    }

    /**
     * 添加一行包含制表符代码
     * @param len 添加对个换行符
     * @param code 代码
     */
    public static StringBuilder tabLine(int len, String code){
        for (int i = 0; i < len; i++) { builder.append("\t"); }
        return builder.append(code).append(";").append(lineBreak);
    }

    /**
     * 添加一行包含制表符代码，不加分号
     * @param len 添加对个换行符
     * @param code 代码
     */
    public static StringBuilder tabLineNo(int len, String code){
        for (int i = 0; i < len; i++) { builder.append("\t"); }
        return builder.append(code).append(lineBreak);
    }

    /**
     * 添加一个类代码
     * @param clazz 类
     */
    public static String clazz(Class<?> clazz){
        importLine(clazz);
        return clazz.getSimpleName();
    }

    /**
     * 添加一个注解类代码
     * @param clazz 类
     */
    public static String anno(Class<?> clazz){
        importLine(clazz);
        return "@" + clazz.getSimpleName();
    }

    /**
     * 添加一个注解类代码，且换行
     * @param clazz 类
     */
    public static StringBuilder annoBr(Class<?> clazz){
        builder.append("@").append(clazz.getSimpleName()).append(lineBreak);
        importLine(clazz);
        return builder;
    }

    /**
     * 添加一行包含import代码
     * @param clazz 类
     */
    public static void importLine(Class<?> clazz){
        importLine(clazz.getName());
    }

    /**
     * 添加一行包含import代码
     * @param className 类名称
     */
    public static void importLine(String className){
        String packages = className.substring(0, className.lastIndexOf("."));
        if(importAll.contains(packages)){
            className = packages + ".*";
        }
        if (className.startsWith("java."))
            javaImports.add("import " + className + ";" + lineBreak);
        else if(className.startsWith("javax."))
            javaxImports.add("import " + className + ";" + lineBreak);
        else
            imports.add("import " + className + ";" + lineBreak);
    }

    /**
     * 添加一个包下的全部类
     * @param packages 包名
     */
    public static void addImportAll(String packages){
        importAll.add(packages);
    }

    /**
     * 导入全部包代码
     */
    private static void importPackage(){
        StringBuilder packages = new StringBuilder();
        packages.append(packageName);
        packages.append(lineBreak);
        packages.append(lineBreak);
        imports.forEach(packages::append);
        packages.append(lineBreak);
        javaxImports.forEach(packages::append);
        javaImports.forEach(packages::append);
        packages.append(lineBreak);
        imports = javaxImports = javaImports = importAll = null;
        builder.insert(0, packages);
    }

    /**
     * 提取全部代码，并清空StringBuilder对象
     */
    public static String save(){
        CodeUtil.importPackage();
        String code = builder.toString();
        builder = null;
        return code;
    }

    /**
     * 下划线转换为驼峰
     *
     * @param line 下划线字符串
     * @param firstIsUpperCase 首字母是否转换为大写
     * @return
     */
    public static String underline2Camel(String line, boolean ... firstIsUpperCase) {
        String str = "";

        if(StringUtils.isBlank(line)){
            return str;
        } else {
            StringBuilder sb = new StringBuilder();
            String [] strArr;
            // 不包含下划线，且第二个参数是空的
            if(!line.contains("_") && firstIsUpperCase.length == 0){
                sb.append(line.substring(0, 1).toLowerCase()).append(line.substring(1));
                str = sb.toString();
            } else if (!line.contains("_") && firstIsUpperCase.length != 0){
                if (!firstIsUpperCase[0]) {
                    sb.append(line.substring(0, 1).toLowerCase()).append(line.substring(1));
                    str = sb.toString();
                } else {
                    sb.append(line.substring(0, 1).toUpperCase()).append(line.substring(1));
                    str = sb.toString();
                }
            } else if (line.contains("_") && firstIsUpperCase.length == 0) {
                strArr = line.split("_");
                for (String s : strArr) {
                    sb.append(s.substring(0, 1).toUpperCase()).append(s.substring(1));
                }
                str = sb.toString();
                str = str.substring(0, 1).toLowerCase() + str.substring(1);
            } else if (line.contains("_") && firstIsUpperCase.length != 0) {
                strArr = line.split("_");
                for (String s : strArr) {
                    sb.append(s.substring(0, 1).toUpperCase()).append(s.substring(1));
                }
                if (!firstIsUpperCase[0]) {
                    str = sb.toString();
                    str = str.substring(0, 1).toLowerCase() + str.substring(1);
                } else {
                    str = sb.toString();
                }
            }
        }
        return str;
    }


    /**
     * 字符串大写字母转下划线
     * @param param
     * @return
     */
    public static String upperCharToUnderLine(String param) {
        Pattern p= Pattern.compile("[A-Z]");
        if(param==null ||param.equals("")){
            return "";
        }
        StringBuilder builder=new StringBuilder(param);
        Matcher mc=p.matcher(param);
        int i=0;
        while (mc.find()) {
            builder.replace(mc.start()+i, mc.end()+i, "_"+mc.group().toLowerCase());
            i++;
        }

        if('_' == builder.charAt(0)){
            builder.deleteCharAt(0);
        }
        return builder.toString();
    }

    /**
     * 转换mysql字段类型到java类型
     * @param columnType
     * @return
     */
    public static Integer getFieldType(String columnType){
        switch (columnType){
            case "time":
            case "datetime":
            case "timestamp":
            case "date":
                return FieldType.Date.getCode();
            case "char":
                return FieldType.Character.getCode();
            case "varchar":
            case "varchar2":
                return FieldType.String.getCode();
            case "decimal":
                return FieldType.BigDecimal.getCode();
            case "float":
                return FieldType.Float.getCode();
            case "bigint":
                return FieldType.Long.getCode();
            case "double":
                return FieldType.Double.getCode();
            case "text":
                return FieldType.Text.getCode();
            case "tinyint":
                return FieldType.Boolean.getCode();
            case "smallint":
                return FieldType.Integer.getCode();
            case "int":
            case "integer":
                return FieldType.Integer.getCode();
            default:
                return FieldType.Object.getCode();

        }
    }
}
